'use strict'

const PostgreModel = require('psqlorm').Model

const fs = require('fs')

const fsp = fs.promises

/**
 * @typedef {object} column
 * @property {string} type - 类型
 * @property {string} refActionDelete - 外键删除后的行为，可以设置为cascade，具体参考数据库文档。
 * @property {string} refActionUpdate - 外键更新后的行为，可以设置为cascade，具体参考数据库文档。
 * @property {string} ref - 外键引用，格式 ModelName:COLUMN，示例：'users:id'
 * @property {string|number} default - 默认值。
 * @property {boolean} notNull - 不允许为null，默认为true。
 * @property {string} oldName - 原column名称，如果要重命名字段，需要oldName指定原有名字。
 * @property {boolean} typeLock - 是否锁定类型，如果为true则会锁定类型，不会更新。
 *
 * 如果指定ref，type会保持和外键引用的字段一致。
 */

let mediaType = {
  IMAGE: 'i',
  AUDIO: 'a',
  VEDIO: 'v'
}

//在column中编辑列字段。

let _table = {
  column: {
    /**
     * @type {column}
     * */
    id: {
      type : 'varchar(12)'
    },

    /**
     * @type {column}
     * */
    name: {
      type : 'varchar(50)',
      default: ''
    },

    tags: {
      type: 'varchar(30)'
    },

    mime_type: {
      type: 'varchar(20)'
    },

    mtype: {
      type: 'char(1)',
      default: mediaType.IMAGE
    },

    /**
     * @type {column}
     * */
    create_time: {
      type : 'bigint',
      default: 0
    },
    
    /**
     * @type {column}
     * */
    update_time: {
      type : 'bigint',
      default: 0
    }
  },

  //索引
  index: [
    'create_time',
    'update_time',
    'tags',
    'mime_type'
  ],

  //唯一索引
  unique: [
    'name'
  ]
}

class Media extends PostgreModel {

  constructor (pqorm) {
    super(pqorm)

    this.modelPath = __dirname

    //以上代码必须存在并且写在前面。

    //主键id前缀，建议不要超过2字符，请确保前缀和idLen的长度 <= 数据库字段的最大长度。
    this.idPre = ''

    //id的长度，默认为12
    //this.idLen = 12

    //默认主键名为id，并且是字符串类型，主键id会自动生成。
    //this.primaryKey = 'id'

    //数据表真正的名称，注意：postgresql不支持表名大写，更改名称请使用小写字母。
    this.tableName = 'media'

    this.table = _table

    this.type = mediaType
  }

  async create (data) {
    data.create_time = data.update_time = Date.now()

    return this.insert(data)
  }

  async remove (name, storagePath) {
    let r = await this.transaction(async (db, ret) => {
      let fname = `${storagePath}/${name}`
      try {
        await fsp.access(fname)
      } catch (err) {
        await fsp.unlink(fname)
      }

      db.delete({name})
      ret.result = `${name} is deleted`
    })

    return r
  }

}

module.exports = Media
